import { WorldState } from "GameLoop/WorldState/worldstate";
import { ABaseDecision } from "./BaseDecision";
import { DecisionConfig } from "./DecisionConfig";
import { MemoryManager } from "./MemoryManager";
import { SpawnDecision } from "./Decisions/Global/SpawnDecision";
import { ProducerCreepDecision } from "./Decisions/room/ProducerCreepDecision";
import { AddRoomDecision } from "./Decisions/room/AddRoomDecision";
import { UpgradeDecision } from "./Decisions/room/creepTask/UpgradeDecision";
import { AddMineRoomDecision } from "./Decisions/room/mineRoom/AddMineRoomDecision";
import { HarvestInnerMineDecision } from "./Decisions/room/creepTask/HarvestInnerMineDecision";
import { PlaceLevelNormalPlanDecision } from "./Decisions/room/roomStrategy/PlaceNormalPlanDecision";
import { ConsumerCreepsDecision } from "./Decisions/room/ConsumerCreepsDecision";
import { BuildTaskDecision } from "./Decisions/room/creepTask/BuildTaskDecision";
import { UpdateEntitymemoryDecision } from "./Decisions/room/roomentity/UpdateEntitymemoryDecision";
import { RepairDecision } from "./Decisions/room/creepTask/RepairDecision";
import { sortBy } from "lodash";
import { PlaceCustomerPlanDecision } from "./Decisions/room/roomStrategy/PlaceCustomerPlanDecision";
import { UpdateRoomEntityDecision } from "./Decisions/room/roomentity/UpdateRoomEntityDecision";
import { SoutDecision } from "./Decisions/room/roomStrategy/SoutDecision";
import { HarvestOutMineDecision } from "./Decisions/room/creepTask/HarvestOutMineDecision";
import { FillDecision } from "./Decisions/room/creepTask/FillDecision";
import { PlaceMinePlanDecision } from "./Decisions/room/roomStrategy/PlaceMinePlanDecision";
import { DefendMyRoomDecision } from "./Decisions/room/roomStrategy/DefendMyRoomDecision";
import { UpdateStationCacheDecision } from "./Decisions/room/roomentity/UpdateStationCacheDecision";
import { ReserveDecision } from "./Decisions/room/creepTask/ReserveDecision";
import { TransportDecision } from "./Decisions/room/creepTask/TransportDecision";
import { ResourceRoomWarDecision } from "./Decisions/room/roomStrategy/ResourceRoomWarDecision";
import { TransportSpawnDecision } from "./Decisions/room/creepTask/TransportSpawnDecision";
import { powerCreepTask } from "./Decisions/room/powerCreepTask/powerCreepTaskDecision";
import { LostRoomDecision } from "./Decisions/Global/LostRoomDecision";
import { TowerRepairRampasrtDecision } from "./Decisions/room/roomStrategy/TowerRepairRampasrtDecision";
import { RampartRepairDecision } from "./Decisions/room/creepTask/RampartRepairDecision";
import { CoreStrategyDecision } from "./Decisions/room/roomStrategy/CoreStrategyDecision";
import { HarvestMinerialDecision } from "./Decisions/room/creepTask/HarvestMinerialDecision";
import { TransportMinerialDecision } from "./Decisions/room/creepTask/TransportMinerialDecision";
import { AddCenterMineRoomDecision } from "./Decisions/room/mineRoom/AddCenterMineRoomDecision";
import { CenterRoomWarDecision } from "./Decisions/room/roomStrategy/CenterRoomWarDecision";
import { PauseRoomTaskDecision } from "./Decisions/room/roomStrategy/PauseRoomTaskDecision";
import { HarvestSingleDecision } from "./Decisions/room/creepTask/HarvestSingleDecision";
import { ResourceDispatchDecision } from "./Decisions/Global/ResourceDispatchDecision";
import { ReactionStrategyDecision } from "./Decisions/room/roomStrategy/ReactionStrategyDecision";
import { TowerHealDecision } from "./Decisions/room/roomStrategy/TowerHealDecision";
import { ProduceLineDecision } from "./Decisions/Global/ProduceLineDecision";
 
import { HarvestDepoDecision } from "./Decisions/room/creepTask/HarvestDepoDecision";
import { AddHallwayRoomDecision } from "./Decisions/room/mineRoom/AddHallwayRoomDecision";
import { HarvestPowerDecision } from "./Decisions/room/creepTask/HarvestPowerDecision";
import { PlaceRampartPlan } from "./Decisions/room/roomStrategy/PlaceRampartPlan";
import { FastDispatchDecision } from "./Decisions/Global/FastDispatchDecision";

type TMapRecord<T extends TEventTypes,V extends TaskType,U extends ABaseDecision<V,T>=ABaseDecision<V,T>>={[P in T]:U[]}
/**
 * 决策管理类 ,决策用于生成任务。决策是固定配置的。
 * 每个事件对应一格决策类，用于生成任务.addTask时，需要.
 * (有没有可能 一个事件可能触发多个决策,决策也不一定触发任务,只改变状态)
 */
/*@profile*/
export class TaskManager
{
    private Decisions!:TMapRecord<TEventTypes,TaskType> ;
    private stateCache:Record<string,number>={};
    private worldstate!:WorldState;
    constructor()
    {
       
    }
    public get getWorldState():WorldState
    {
        return this.worldstate
    }

    // 初始化属性
    private initializeAttribute()
    {
        this.Decisions={
            "LostRoomEvent":[this.newDecision(LostRoomDecision )],
            // "SpawnEvent":[this.newDecision(SpawnDecision )],
            "FactoryProduce":[this.newDecision(ProduceLineDecision )],
            "KeepEvent":[
                this.newDecision(ProducerCreepDecision ),
                this.newDecision(ConsumerCreepsDecision),
            ],
            // AddRoomEvent 房间初始化的时候
            "AddRoomEvent":[
                this.newDecision(AddRoomDecision),
                this.newDecision(ProducerCreepDecision ),
                this.newDecision(ConsumerCreepsDecision),
                this.newDecision(UpgradeDecision),  
                this.newDecision(HarvestInnerMineDecision),
                this.newDecision(HarvestOutMineDecision),
                
               
                this.newDecision(BuildTaskDecision),
                // this.newDecision(PlaceCustomerPlanDecision),
                this.newDecision(UpdateEntitymemoryDecision ),
                this.newDecision(SoutDecision ),
                this.newDecision(PlaceMinePlanDecision),
                this.newDecision(PlaceLevelNormalPlanDecision),
            ],
            "AddHallwayRoom":[
                this.newDecision(AddHallwayRoomDecision),
            ],
            "AddMineRoom":[
                this.newDecision(AddMineRoomDecision),
                this.newDecision(AddCenterMineRoomDecision),
               
                this.newDecision(ProducerCreepDecision ),
                this.newDecision(HarvestOutMineDecision),
                this.newDecision(PlaceMinePlanDecision)
            ],
            "HarvestEvent":[
                this.newDecision(HarvestInnerMineDecision),
            ],
            "HarvestDepo":[
                this.newDecision(HarvestDepoDecision),
            ],
            "HarvestPower":[
                this.newDecision( HarvestPowerDecision)
            ],
            "LevelUp":[ 
                this.newDecision(UpdateRoomEntityDecision),
                this.newDecision(ProducerCreepDecision ),
                this.newDecision(ConsumerCreepsDecision),
                this.newDecision(HarvestOutMineDecision),
                this.newDecision(PlaceLevelNormalPlanDecision),
                // this.newDecision(PlaceCustomerPlanDecision),
                this.newDecision(PlaceMinePlanDecision),
                
            ],
            "PlaceSite":[ 
                this.newDecision(BuildTaskDecision)
            ],
            "EnengyCapacityUp":[ 
                this.newDecision(UpdateEntitymemoryDecision ),
                // this.newDecision(ConsumerCreepsDecision),
            ],
            "RepairEvent":[
                this.newDecision(RepairDecision),
                
            ],
            "RepairRampartEvent":[
                this.newDecision(RampartRepairDecision),
            ],
            "BuildComplete":[
                this.newDecision(ProducerCreepDecision ),
                this.newDecision(ConsumerCreepsDecision),
                this.newDecision(UpgradeDecision), 
                this.newDecision(BuildTaskDecision),
                this.newDecision(UpdateStationCacheDecision),
                this.newDecision(HarvestInnerMineDecision),
            ],
            "BuildItemComplete":[
                this.newDecision(UpdateEntitymemoryDecision ),
                this.newDecision(UpdateStationCacheDecision),
                this.newDecision(TowerRepairRampasrtDecision)
            ],
            "FillAnyStore":[
                this.newDecision(FillDecision)
            ],
            "DefendEvent":[
                this.newDecision(DefendMyRoomDecision)
            ],
            "BuildEvent":
            [
                this.newDecision(BuildTaskDecision),
                this.newDecision(UpdateEntitymemoryDecision )
            ],
            "ReserveEvent":
            [
                this.newDecision(ReserveDecision )
            ],
            "Tick":
            [
                this.newDecision(TransportDecision),
                // this.newDecision(TransportSpawnDecision),
                this.newDecision(CoreStrategyDecision),
                this.newDecision(HarvestMinerialDecision),
                this.newDecision(ReactionStrategyDecision),
                this.newDecision(PlaceRampartPlan),
                // this.newDecision(TransportMinerialDecision)
            ],
            "HealCreep":[
                this.newDecision(TowerHealDecision)
            ],
            "Observe":[
                this.newDecision(SoutDecision)
            ],
            "ResourceBlance":
            [
                this.newDecision(ResourceDispatchDecision)
            ],
            "Harvest":
            [
                this.newDecision(HarvestSingleDecision),
            ]
            ,
            "DefendMineRoom":
            [
                this.newDecision(ResourceRoomWarDecision)
            ],"PowerEvent":
            [
                this.newDecision(powerCreepTask)
            ],
            "DefendCenterRoom":
            [
                this.newDecision(CenterRoomWarDecision)
            ],
            "PauseEvent":
            [
                this.newDecision( PauseRoomTaskDecision)
            ],
            "Distribute":
            [
                this.newDecision( FastDispatchDecision)
            ]
        }
    }
    private newDecision<T extends ABaseDecision<TaskType,TEventTypes>>(c:{new (world:WorldState):T})
    {
        return new c(this.worldstate);
    }
    /**
    * 初始化
    */
    public init(world:WorldState)
    {
        this.worldstate = world;
        this.initializeAttribute();
        // 全局的
        const _this = this;
        for(const e of DecisionConfig[Game.shard.name])
        {
            this.getWorldState.listenEvent(e,this.makeDecision.bind(this));
            
        }
        // 
         
    }
    /**
     * 更新房间的事件绑定
 * */ 
    public upadteListen()
    {
        // 1. 注册全局的
        // 2.根据房间的类型。注册不同的任务决策
        for(const  k in Game.rooms)
        {
            const type = Game.rooms[k].getType();
            Game.rooms[k].initAttributes()
            if(type &&   DecisionConfig[type])
            {
                if(this.stateCache[k] && this.stateCache[k] == type)
                {
                    // 已经添加过了
                    continue;
                }
                this.registerRoomListen(Game.rooms[k],DecisionConfig[type]);
            }
        }
    }

    /**
     * 监听事件
     * @param room 
     * @param config 
     */
    private registerRoomListen(room:Room,config:TEventTypes[])
    {
        this.stateCache[room.name]= room.getType();
        this.getWorldState.unregisterEvent(room.name);  // 先取消掉之前注册的事件
        for(const e of config)
        {
            this.getWorldState.listenEvent(e,this.makeDecision.bind(this),room.name);
        }
    }

    /**
     * 因为不是所有的事件都是由监听获得的。也可能是由其他实体主动触发的
     * 通知事件
     * @param type 
     * @param event 
     * @param region 
     */
    public notifyEvent<T extends TEventTypes=TEventTypes>(type:T,event:IWorldEvents[T],region:string):void
    {
        //global.Log.Info(`1 指定决策 ${type} ->${JSON.stringify(event)}`);
        this.makeDecision(type,event,region);
        //global.Log.Info(`2 指定决策 ${type} ->${JSON.stringify(event)}`);
    }

    /**
     * 生成任务
     * @param type 事件类型
     * @param event 事件参数
     * @param region 
     */
    private makeDecision<T extends TEventTypes=TEventTypes>(type:T,event:IWorldEvents[T],region:string):void
    {
        for(const d of this.Decisions[type])
        {

            if(d.isExpired(event,region))
            {
                // 过期了 则重新生成任务。对于没有返回任务的。说明都是可以立即执行的。所以不用返回任务对象来等待执行
                const task = d.makeTask(event,region);
                if(task)
                {
                    // 任务类型时孵化任务时特化处理,孵化任务需要优先级排序
                   // this.debugTask(task.task as any,"W5N8_source_14_13");
                    this.addTask(type, task.task,task.region,task.isunique);
                    //this.debugTask(task.task as any,"W5N8_source_14_13");
                }
            }
        }
        
    }

    /**
     * 向指定的事件添加任务
     * @param eventkey 事件名称
     * @param task 任务
     * @param region 事件范围
     * @param isunique 本次添加的任务是否是在同类型任务分类里，是唯一的
     * @returns 
     */
    private addTask<T extends TEventTypes>(eventkey:T,task:ITaskDeclare[TaskType][],region:string,isunique:boolean):boolean
    {
        // 添加保存任务;保存任务直接操作内存，而不是操作room对象。因为可能使用的room不是自己的，
        const cache = MemoryManager.getMemory(region);

        for(const  e of task)
        {
            this.addNewTask(region,cache,e);
            
        }
         
        return true;
    }

    public addNewTask<T extends TaskType>(region:string,cache:IMemoryCache,e:ITaskDeclare[T]):boolean
    {
        if(cache.Tasks[e.type ])
        {
            if(cache.Tasks[e.type ].findIndex(t=>t.id == e.id)>-1)
            {
                return false;
            }
        }
        else
        {
            cache.Tasks[e.type ]=[]
        }
        const index = cache.Tasks[e.type ].findIndex(t=>t.priority<e.priority);
        if(index>=0)
        {
            cache.Tasks[e.type ].splice(index,0,e);
        }
        else
        {
            cache.Tasks[e.type ].push(e);
        }
       
        global.Log.Info(`[${region}] 新增任务 ${e.type},${e.id},${e.data?.type}`);
        return true;
    }
     
    private debugTask(Task:ITaskDeclare["creep"],id="")
    {
        // if(Task.id == id)
        if(Task.data?.creeps)
        {
            global.Log.Info(`任务调试  ${Task.id}->${JSON.stringify(Task.data.creeps)}`);
        }
        
         
    }
}